package com.zhangxin.aiInterview.manager.xfapi.websocket.ttsmodel;

import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import com.zhangxin.aiInterview.constant.FileConstant;
import com.zhangxin.aiInterview.manager.cos.CosManager;
import com.zhangxin.aiInterview.manager.wsserver.WsManager;
import com.zhangxin.aiInterview.manager.wsserver.enums.WsMessageTypeEnum;
import com.zhangxin.aiInterview.manager.wsserver.model.WsResponseMessage;
import com.zhangxin.aiInterview.utils.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 语音合成流式 WebAPI 接口调用示例 接口文档（必看）：https://www.xfyun.cn/doc/tts/online_tts/API.html
 * 发音人使用方式：登陆开放平台https://www.xfyun.cn/后，到控制台-我的应用-语音合成-添加试用或购买发音人，添加后即显示该发音人参数值
 * 错误码链接：https://www.xfyun.cn/document/error-code （code返回错误码时必看）
 * 小语种需要传输小语种文本、使用小语种发音人vcn、tte=unicode以及修改文本编码方式
 *
 * @author xlliu24
 */
@Slf4j
@Deprecated
public class TtsWs {
    // 地址与鉴权信息
    public static final String hostUrl = "https://tts-api.xfyun.cn/v2/tts";
    // 均到控制台-语音合成页面获取
    public static final String APISecret = "MzdhNDEzNzVkMDcyZDhhZTM3MWNjODhj";
    public static final String APIKey = "cd5245ddf5444cfcedd25b57a29b4c0b";

    public static final String MP3_OUTPUT_FILE_PATH = "E:\\project\\AI_Interview\\AI_Interview_backend\\src\\main\\resources\\" + System.currentTimeMillis() + ".mp3";
    // json
    public static final Gson gson = new Gson();

    /**
     * 初始化连接
     * @param userId 用户id
     * @throws Exception
     */
    public static void init(Long userId) throws Exception {
        String wsUrl = getAuthUrl(hostUrl, APIKey, APISecret).replace("https://", "wss://");
        OutputStream outputStream = Files.newOutputStream(Paths.get(MP3_OUTPUT_FILE_PATH));
        websocketWork(wsUrl, outputStream,userId);
    }

    /**
     * 建立websocket连接
     * @param wsUrl ws服务器地址
     * @param outputStream 输出流
     * @param userId 用户id
     */
    public static void websocketWork(String wsUrl, OutputStream outputStream,Long userId) {
        try {
            URI uri = new URI(wsUrl);
            //定义ws连接消息监听器
            WebSocketClient webSocketClient = new WebSocketClient(uri) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    System.out.println("tts ws建立连接成功...");
                }
                @Override
                public void onMessage(String text) {
                    JsonParse myJsonParse = gson.fromJson(text, JsonParse.class);
                    if (myJsonParse.code != 0) {
                        System.out.println("发生错误，错误码为：" + myJsonParse.code);
                        System.out.println("本次请求的sid为：" + myJsonParse.sid);
                    }
                    if (myJsonParse.data != null) {
                        try {
                            byte[] textBase64Decode = Base64.getDecoder().decode(myJsonParse.data.audio);
                            //写入pcm文件
                            outputStream.write(textBase64Decode);
                            outputStream.flush();

                            if (myJsonParse.data.status == 2) {
                                //释放输出流资源
                                outputStream.close();
                                TtsWsManager.removeConnection(userId);
                                //上传到cos
                                CosManager cosManager = SpringContextUtil.getBean(CosManager.class);
                                //COS上传路径
                                String path =String.format("/%s/%s/%s","ai_interview/ai_interview_audio",userId,System.currentTimeMillis()+".mp3");
                                cosManager.putObject(path, MP3_OUTPUT_FILE_PATH);
                                //返回音频访问路径
                                path = FileConstant.COS_HOST + path;
                                System.out.println("COS文件上传成功，访问路径为==>" + path);
                                //获取客户端ws连接
                                WebSocketSession wsSession = WsManager.getConnection(userId);
                                WsResponseMessage wsResponseMessage = new WsResponseMessage(WsMessageTypeEnum.AUDIO.getValue(), path);
                                //返回音频访问路径给客户端
                                wsSession.sendMessage(new TextMessage(JSONUtil.toJsonStr(wsResponseMessage)));
                            }
                        }catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
                @Override
                public void onClose(int i, String s, boolean b) {
                    System.out.println("tts ws连接已关闭，本次请求完成...");
                    //清理用户连接
                    TtsWsManager.removeConnection(userId);
                    //删除MP3文件
                    try {
                        Files.delete(Paths.get(MP3_OUTPUT_FILE_PATH));
                    } catch (Exception e) {
                        System.out.println("删除MP3文件失败");
                    }
                }
                @Override
                public void onError(Exception e) {
                    System.out.println("tts ws连接异常，异常信息为：" + e.getMessage());
                }
            };
            // 建立ws连接
            webSocketClient.connect();
            while (!webSocketClient.getReadyState().equals(WebSocket.READYSTATE.OPEN)) {
                System.out.println("正在连接...");
                Thread.sleep(100);
            }
            //管理连接
            TtsWsManager.addOrUpdateConnection(userId, webSocketClient);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    //region
    // 鉴权方法
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        //System.out.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        return httpUrl.toString();
    }

    //返回的json结果拆解
    class JsonParse {
        int code;
        String sid;
        Data data;
    }

    class Data {
        int status;
        String audio;
    }
    //endregion
}
